﻿//Copyright (C) <2013>  <jonathan cleeve norton> All Rights Reserved 
//Contact jon.norton@fin-plus.co.uk website <http://www.fin-plus.co.uk/>
using System;
using System.ComponentModel;
using FinPlusCommon;
using log = Logger.Logger;
using u = FinPlusUtility.Utility;

namespace FinPlusComponents
{
    public class QLParseBondTrade : FinPlusComponent
    {
        private enum Params { ParseTradeAction, ResponseAction, Bond, BuySell, Instrument, Settle, QuoteAccept, QuoteRef, TradeId, Quote, Size, FunctionName, FixedRateBond, FloatingRateBond, ZeroCouponBond, Book, Counterparty, MarketName, CacheName, TempId, BondName, CurveName, Nominal, Settlement, Price }
        private enum BondBuilds { FixedRateBondBuild, FloatingRateBondBuild, ZeroCouponBondBuild, Bond }
        private readonly IFinPlusComp _instrumentBuildConn, _tradeAdaptorConn;
        private readonly FinPlusConnectDB _tradeSaveConn;
        private readonly IFunction _tradeAdaptor;

        //construct
        public QLParseBondTrade(IFinPlusComp instrumentBuilds, IFinPlusComp tradeAdaptors, IFinPlusComp tradeSave)
        {
            _instrumentBuildConn = instrumentBuilds;
            _tradeAdaptorConn = tradeAdaptors;
            _tradeSaveConn = (FinPlusConnectDB)tradeSave;
            _tradeAdaptor = _tradeAdaptorConn.Adaptor.First("Name='InstrumentType' And Value='Bond'");
            _tradeAdaptor.Get(Params.ParseTradeAction.ToString(), Parse_Trade);
            IsValid = true;
        }

        //common control interface
        public override void Dispose()
        {
            try
            {
                if (_tradeSaveConn != null)
                    _tradeSaveConn.Dispose();
            }
            catch (Exception e)
            {
                IsValid = log.Log(Logger.Level.Warning, Id, Config, e.Message, e);
            }
        }

        public override void CmdExecute(IFunction command)
        {
            try
            {
                CmdCapture(command);

                switch ((Cmds)Enum.Parse(typeof(Cmds), command.Name, true))
                {
                    case Cmds.QuoteAccept: ExecutionParse(command); break;
                    case Cmds.QuoteAcceptPublish: ExecutionParse(command); break;
                    default: throw new FormatException(string.Format("event not recognised {0}", command.Name));
                }
            }
            catch (CmdExecuteException e)
            {
                IsValid = log.Log(Logger.Level.Error, Id, Config, e.Message, e);
            }
        }

        //private
        private bool ExecutionParse(IFunction func)
        {
            try
            {
                //trade parse
                var instrument = func[Params.Instrument.ToString()].ToString();
                var instrumentBuild = _instrumentBuildConn.Adaptor.First("Name='Instrument' And Value='" + instrument + "'");

                IFunction trade;
                switch (u.EnumParse<BondBuilds>(instrumentBuild[Params.FunctionName.ToString()].ToString(), BondBuilds.Bond))
                {
                    case BondBuilds.FixedRateBondBuild: trade = new Function(Params.FixedRateBond.ToString()); break;
                    case BondBuilds.FloatingRateBondBuild: trade = new Function(Params.FloatingRateBond.ToString()); break;
                    case BondBuilds.ZeroCouponBondBuild: trade = new Function(Params.ZeroCouponBond.ToString()); break;
                    default: trade = new Function(Params.Bond.ToString()); break;
                }

                trade.Add(Params.Book.ToString(), func[Params.Book.ToString()].ToString());
                trade.Add(Params.Counterparty.ToString(), func[Params.Counterparty.ToString()].ToString());
                trade.Add(Params.MarketName.ToString(), string.Empty);
                trade.Add(Params.CacheName.ToString(), string.Empty);
                trade.Add(Params.TradeId.ToString(), func[Params.QuoteRef.ToString()].ToString());
                trade.Add(Params.BondName.ToString(), func[Params.Instrument.ToString()].ToString());
                trade.Add(Params.CurveName.ToString(), string.Empty);

                if(func.Name.Equals(Params.QuoteAccept.ToString()))
                    trade.Add(Params.Nominal.ToString(), (func[Params.BuySell.ToString()].Equals("Buy") ? -1 : 1) * (double)func.Value(Params.Size.ToString()));
                else
                    trade.Add(Params.Nominal.ToString(), (func[Params.BuySell.ToString()].Equals("Buy") ? 1 : -1) * (double)func.Value(Params.Size.ToString()));
                
                trade.Add(Params.Settlement.ToString(), (DateTime)func.Value(Params.Settle.ToString()));
                trade.Add(Params.Price.ToString(), (double)func.Value(Params.Quote.ToString()));

                //save bond
                _tradeSaveConn.Save(trade);

                //respond with trade for testing
                trade.Add(Params.Instrument.ToString(), instrument); 
                _tradeAdaptor.Get(Params.ResponseAction.ToString()).Set(trade);

                return true;
            }
            catch (Exception e)
            {
                return IsValid = log.Log(Logger.Level.Error, Id, Config, func.ToString(), e);
            } 
        }

        //cmds
        private enum Cmds { QuoteAccept, QuoteAcceptPublish };

        //events
        private void Parse_Trade(object s, PropertyChangedEventArgs a) { CmdRouter(s); }//QuoteAccept && QuotePublishAccept
    }
}
